/*
 *  Material.cpp
 *  EidoTron
 *
 *  Created by Luca Di Franco on 10/03/11.
 *  Copyright 2011 Luca Di Franco. All rights reserved.
 *
 */

#include "Material.h"

#include <SDL_opengl.h>
#include <iostream>
#include <fstream>

#include "Image.h"
#include "../Utilities/StringExtension.h"

using std::fstream;
using std::cout;

Material::Material()
{
	name[0] = 'n', name[1] = 'o', name[2] = 'n', name[3] = 'e', name[4] = '\0';
	Ka[0] = Ka[1] = Ka[2] = 0.2f;
	Kd[0] = Kd[1] = Kd[2] = 0.8f;
	Ks[0] = Ks[1] = Ks[2] = 1.0f;
	shininess = 0.0f;
	KdTexture = NULL;
}

Material::~Material()
{
	if (KdTexture != NULL)
		delete KdTexture;
}

vector< Material* >* Material::materialsFromFile(const char* fileName)
{
	fstream* fileStream = new fstream(fileName, fstream::in);
	if (fileStream->fail())
	{
		cout << "File " << fileName << " not found!\nSYSTEM WILL EXIT";
		exit(EXIT_FAILURE);
	}
	
	char* line = new char[256];
	Material* currMaterial = NULL;
	vector<Material*>* materials = new vector<Material*>;
	while (!fileStream->eof())
	{
		fileStream->getline(line, 256);
		if (strncmp(line, "newmtl ", 7) == SAME_STRING)
		{
			currMaterial = new Material;
			sscanf(line, "newmtl %s", currMaterial->name);
			materials->push_back(currMaterial);
		}
		else if (strncmp(line, "Ka ", 3) == SAME_STRING)
			sscanf(line, "Ka %f %f %f", &(currMaterial->Ka[0]), &(currMaterial->Ka[1]), &(currMaterial->Ka[2]));
		else if (strncmp(line, "Kd ", 3) == SAME_STRING)
			sscanf(line, "Kd %f %f %f", &(currMaterial->Kd[0]), &(currMaterial->Kd[1]), &(currMaterial->Kd[2]));
		else if (strncmp(line, "Ks ", 3) == SAME_STRING)
			sscanf(line, "Ks %f %f %f", &(currMaterial->Ks[0]), &(currMaterial->Ks[1]), &(currMaterial->Ks[2]));
		else if (strncmp(line, "Ns ", 3) == SAME_STRING)
			sscanf(line, "Ns %f", &(currMaterial->shininess));
		else if ((strncmp(line, "Ts ", 3) == SAME_STRING) || (strncmp(line, "d ", 2) == SAME_STRING))
			sscanf(line, "Ts %f", &(currMaterial->alpha));
		else if (strncmp(line, "map_Kd ", 7) == SAME_STRING)
		{
			char textureFileName[128];
			sscanf(line, "map_Kd %s", textureFileName);
			currMaterial->KdTexture = Image::loadBMP(textureFileName);
		}
	}
	fileStream->close();
	return materials;
}

Material* Material::find(vector< Material* >* materials, const char* materialName)
{
	for (vector<Material*>::iterator iter = materials->begin(); iter < materials->end(); iter++)
	{
		if (strcmp((*iter)->name, materialName) == SAME_STRING)
			return (*iter);
	}
	return NULL;
}

void Material::startUse()
{
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Ka);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Kd);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Ks);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
	if (KdTexture != NULL)
	{
		KdTexture->loadMipmappedTexture();
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, KdTexture->textureId);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	}
}

void Material::stopUse()
{
	if (KdTexture != NULL)
		glDisable(GL_TEXTURE_2D);
}

void Material::mulColor(float* color)
{
	for (int i = 0; i < 3; i++)
	{
		Ka[i] *= color[i];
		Kd[i] *= color[i];
		Ks[i] *= color[i];
	}
}